﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Drawing2D;
using System.Reflection;
using System.Windows.Forms;
using HML.Design;

namespace HML
{
    /// <summary>
    /// Int角度控件
    /// </summary>
    [Description("Int角度控件")]
    [DefaultProperty("Value")]
    [DefaultEvent("AngleChanged")]
    [TypeConverter(typeof(PropertyOrderConverter))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(IntAngle), "Controls.IntAngle.Resources.IntAngle.bmp")]
    public class IntAngle : DpiControl, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(IntAngle)).GetName().Name, typeof(IntAngle).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        private SkinController skinController = null;
        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinController SkinController
        {
            get { return this.skinController; }
            set
            {
                if (this.skinController == value)
                    return;

                if (this.skinController != null)
                    this.skinController.RemoveSkinObject(this);

                this.skinController = value;

                if (this.skinController != null)
                    this.skinController.AddSkinObject(this);
            }
        }

        private SkinEnabledState skinEnabled= SkinEnabledState.Auto;
        /// <summary>
        /// 主题是否启用
        /// </summary>
        [Description("主题是否启用")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.Auto)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;
                this.OnSkinChanged();
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;
                this.OnSkinChanged();
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);
                return this.stateAppearance;
            }
        }

        /// <summary>
        /// 主题已更改
        /// </summary>
        public virtual void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);
            this.Invalidate();
        }

        private ISkinObject followSkinObject = null;
        /// <summary>
        /// 主题设置跟随指定主题对象（自己的设置不再生效，提供给代码使用）
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ISkinObject FollowSkinObject
        {
            get { return this.followSkinObject; }
            set
            {
                if (this.followSkinObject == value)
                    return;

                this.followSkinObject = value;
                this.OnSkinChanged();
            }
        }

        public virtual bool GetSkinObjectSkinStateCore()
        {
            return SkinManager.GetSkinObjectSkinState(this.FollowSkinObject ?? this);
        }

        void ISkinObject.InitializeInvalidate()
        {
            throw new NotImplementedException();
        }

        void ISkinObject.Invalidate()
        {
            this.Invalidate();
        }

        #endregion

        #region 新增事件

        private static readonly object EventValueChanged = new object();
        /// <summary>
        /// Value值更改事件
        /// </summary>
        [Description("Value值更改事件")]
        public event EventHandler ValueChanged
        {
            add { Events.AddHandler(EventValueChanged, value); }
            remove { Events.RemoveHandler(EventValueChanged, value); }
        }

        public delegate void ValueFormatEventHandler(object sender, IntAngleFormatEventArgs e);
        private static readonly object EventValueFormat = new object();
        /// <summary>
        /// Value值格式化事件
        /// </summary>
        [Description("Value值格式化事件")]
        public event ValueFormatEventHandler ValueFormat
        {
            add { Events.AddHandler(EventValueFormat, value); }
            remove { Events.RemoveHandler(EventValueFormat, value); }
        }

        #endregion

        #region 停用事件

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler PaddingChanged
        {
            add { base.PaddingChanged += value; }
            remove { base.PaddingChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabIndexChanged
        {
            add { base.TabIndexChanged += value; }
            remove { base.TabIndexChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TabStopChanged
        {
            add { base.TabStopChanged += value; }
            remove { base.TabStopChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyEventHandler KeyDown
        {
            add { base.KeyDown += value; }
            remove { base.KeyDown -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyEventHandler KeyUp
        {
            add { base.KeyUp += value; }
            remove { base.KeyUp -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event KeyPressEventHandler KeyPress
        {
            add { base.KeyPress += value; }
            remove { base.KeyPress -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event PreviewKeyDownEventHandler PreviewKeyDown
        {
            add { base.PreviewKeyDown += value; }
            remove { base.PreviewKeyDown -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler TextChanged
        {
            add { base.TextChanged += value; }
            remove { base.TextChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ImeModeChanged
        {
            add { base.ImeModeChanged += value; }
            remove { base.ImeModeChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageChanged
        {
            add { base.BackgroundImageChanged += value; }
            remove { base.BackgroundImageChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackgroundImageLayoutChanged
        {
            add { base.BackgroundImageLayoutChanged += value; }
            remove { base.BackgroundImageLayoutChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler BackColorChanged
        {
            add { base.BackColorChanged += value; }
            remove { base.BackColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler ForeColorChanged
        {
            add { base.ForeColorChanged += value; }
            remove { base.ForeColorChanged -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler Click
        {
            add { base.Click += value; }
            remove { base.Click -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event EventHandler DoubleClick
        {
            add { base.DoubleClick += value; }
            remove { base.DoubleClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseClick
        {
            add { base.MouseClick += value; }
            remove { base.MouseClick -= value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new event MouseEventHandler MouseDoubleClick
        {
            add { base.MouseDoubleClick += value; }
            remove { base.MouseDoubleClick -= value; }
        }
        #endregion

        #region 新增属性

        private int plateBackShadowAngle = 300;
        /// <summary>
        /// 表盘背景阴影颜色角度
        /// </summary>
        [Description("表盘背景阴影颜色角度")]
        [Category("杂项")]
        [PropertyOrder(-194)]
        [DefaultValue(300)]
        [Editor(typeof(IntAngleEditor), typeof(UITypeEditor))]
        public int PlateBackShadowAngle
        {
            get { return this.plateBackShadowAngle; }
            set
            {
                if (value < 0)
                    value = 0;
                if (value > 360)
                    value = 360;
                if (this.plateBackShadowAngle == value)
                    return;

                this.plateBackShadowAngle = value;
                this.Invalidate();
            }
        }

        private float pointerSizePercentage = 15f;
        /// <summary>
        /// 角度针Size百分比 (相对于控件Size  0》 《30%)
        /// </summary>
        [Description("角度针Size百分比 (相对于控件Size  0》 《30%)")]
        [Category("杂项")]
        [PropertyOrder(-192)]
        [DefaultValue(15f)]
        public float PointerSizePercentage
        {
            get { return this.pointerSizePercentage; }
            set
            {
                if (value > 30)
                    value = 30;
                if (this.pointerSizePercentage == value || value <= 0)
                    return;

                this.pointerSizePercentage = value;
                this.Invalidate();
            }
        }

        private bool referenceAngleVisible = false;
        /// <summary>
        /// 是否显示参考角度线
        /// </summary>
        [Description("是否显示参考角度线")]
        [Category("杂项")]
        [PropertyOrder(-190)]
        [DefaultValue(false)]
        public bool ReferenceAngleVisible
        {
            get { return this.referenceAngleVisible; }
            set
            {
                if (this.referenceAngleVisible == value)
                    return;

                this.referenceAngleVisible = value;
                this.Invalidate();
            }
        }

        private int referenceAngle = 0;
        /// <summary>
        /// 角度针参考角度 (x轴开始)
        /// </summary>
        [Description("角度针参考角度 (x轴开始)")]
        [Category("杂项")]
        [PropertyOrder(-188)]
        [DefaultValue(0)]
        [Editor(typeof(IntAngleEditor), typeof(UITypeEditor))]
        public int ReferenceAngle
        {
            get { return this.referenceAngle; }
            set
            {
                if (value < 0)
                    value = 0;
                if (value > 360)
                    value = 360;
                if (this.referenceAngle == value)
                    return;

                this.referenceAngle = value;
                this.mousedownobject = false;
                this.pointer_lock_area = 0;
                this.Invalidate();

            }
        }

        private bool valueVisible = false;
        /// <summary>
        /// 是否显示角度文本
        /// </summary>
        [Description("是否显示角度文本")]
        [Category("杂项")]
        [PropertyOrder(-186)]
        [DefaultValue(false)]
        public bool ValueVisible
        {
            get { return this.valueVisible; }
            set
            {
                if (this.valueVisible == value)
                    return;

                this.valueVisible = value;
                this.Invalidate();
            }
        }

        private int value = 0;
        /// <summary>
        /// 角度值
        /// </summary>
        [Description("角度值")]
        [Category("杂项")]
        [PropertyOrder(-182)]
        [DefaultValue(0)]
        [Editor(typeof(IntAngleEditor), typeof(UITypeEditor))]
        public int Value
        {
            get { return this.value; }
            set
            {
                if (value < 0)
                    value = 0;
                if (value > 360)
                    value = 360;
                if (this.value == value)
                    return;

                this.value = value;
                this.Invalidate();

                this.OnValueChanged(EventArgs.Empty);
            }
        }

        private bool readOnly = false;
        /// <summary>
        /// 是否只读
        /// </summary>
        [Description("是否只读")]
        [Category("杂项")]
        [PropertyOrder(-180)]
        [DefaultValue(false)]
        public bool ReadOnly
        {
            get { return this.readOnly; }
            set
            {
                if (this.readOnly == value)
                    return;

                this.readOnly = value;
                this.Invalidate();
            }
        }

        private bool allowLoopChanged = false;
        /// <summary>
        /// 是否允许鼠标循环移动修改角度值
        /// </summary>
        [Description("是否允许鼠标循环移动修改角度值")]
        [Category("杂项")]
        [PropertyOrder(-176)]
        [DefaultValue(false)]
        public bool AllowLoopChanged
        {
            get { return this.allowLoopChanged; }
            set
            {
                if (this.allowLoopChanged == value)
                    return;

                this.allowLoopChanged = value;
                this.mousedownobject = false;
                this.pointer_lock_area = 0;
                this.Invalidate();
            }
        }

        #endregion

        #region 重写属性

        protected override Size DefaultSize
        {
            get { return new Size(60, 60); }
        }

        protected override ImeMode DefaultImeMode
        {
            get { return ImeMode.Disable; }
        }

        #endregion

        #region 停用属性

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Padding Padding
        {
            get { return base.Padding; }
            set { base.Padding = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new int TabIndex
        {
            get { return base.TabIndex; }
            set { base.TabIndex = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new bool TabStop
        {
            get { return base.TabStop; }
            set { base.TabStop = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ImeMode ImeMode
        {
            get { return base.ImeMode; }
            set { base.ImeMode = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Image BackgroundImage
        {
            get { return base.BackgroundImage; }
            set { base.BackgroundImage = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override ImageLayout BackgroundImageLayout
        {
            get { return base.BackgroundImageLayout; }
            set { base.BackgroundImageLayout = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color BackColor
        {
            get { return this.StyleAppearance.BackColor; }
            set { }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Color ForeColor
        {
            get { return this.StyleAppearance.TextColor; }
            set { }
        }

        #endregion

        #region 字段

        /// <summary>
        /// 当前鼠标已按下的对象
        /// </summary>
        private bool mousedownobject = false;
        /// <summary>
        /// 当前鼠标已按下的角度针角度差距
        /// </summary>
        private int mousedownoangledisparity = 0;

        /// <summary>
        /// 角度针上一次所在区域
        /// </summary>
        private int pointer_last_area = 0;
        /// <summary>
        /// 角度针当前所在区域
        /// </summary>
        private int pointer_current_area = 0;
        /// <summary>
        /// 当前锁定区域（用于防止越过最大最小值，0为没有任何区域要锁定）
        /// </summary>
        private int pointer_lock_area = 0;

        /// <summary>
        /// 内容内边距
        /// </summary>
        private int contentPadding = 2;

        #endregion

        public IntAngle()
        {
            SetStyle(ControlStyles.UserPaint, true);
            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.StandardClick, false);//自定义单击事件逻辑
            SetStyle(ControlStyles.StandardDoubleClick, false);//停用双加事件

            this.TabStop = false;
            this.OnSkinChanged();
        }

        #region 重写

        protected override void OnScaleDpiChangedInitialize()
        {
            this.Invalidate();
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            base.OnPaintBackground(pevent);

            Graphics g = pevent.Graphics;

            SolidBrush back_sb = new SolidBrush(this.StyleAppearance.BackColor);
            g.FillRectangle(back_sb, this.ClientRectangle);
            back_sb.Dispose();
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            Graphics g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            int scale_contentPadding = (int)Math.Ceiling(this.contentPadding * this.ScaleDpi);
            int min = (int)Math.Max(0, Math.Min(this.Width - scale_contentPadding * 2, this.Height - scale_contentPadding * 2));
            int scale_pointer_radius = Math.Max(0, (int)(min * this.PointerSizePercentage / 100f)) / 2;
            int scale_pointer_padding = Math.Max(0, scale_pointer_radius);
            Size scale_referenceAngleLineSize = !this.ReferenceAngleVisible ? new Size(0, 0) : new Size((int)Math.Max(2, Math.Max(4, (int)Math.Ceiling(scale_pointer_radius / 4f)) / 3f), Math.Max(4, (int)Math.Ceiling(scale_pointer_radius / 4f)));
            int scale_plate_radius = Math.Max(0, (min - scale_referenceAngleLineSize.Height)) / 2;

            Point plate_center_point = new Point(this.ClientRectangle.X + this.ClientRectangle.Width / 2, this.ClientRectangle.Y + this.ClientRectangle.Height / 2);
            RectangleF plate_rect = new RectangleF(plate_center_point.X - scale_plate_radius, plate_center_point.Y - scale_plate_radius, scale_plate_radius * 2, scale_plate_radius * 2);

            //参考角度线
            if (this.ReferenceAngleVisible)
            {
                Pen angleLine_pen = new Pen(this.StyleAppearance.ReferenceAngleLineColor, scale_referenceAngleLineSize.Width);
                g.DrawLine(angleLine_pen, ControlHelper.CalculatePointForAngle(plate_center_point, scale_plate_radius, this.ReferenceAngle), ControlHelper.CalculatePointForAngle(plate_center_point, scale_plate_radius + scale_referenceAngleLineSize.Height, this.ReferenceAngle));
                angleLine_pen.Dispose();
            }

            //表盘
            LinearGradientBrush plate_lgb = new LinearGradientBrush(plate_rect, this.StyleAppearance.PlateBackColor, this.StyleAppearance.PlateBackShadowColor, this.PlateBackShadowAngle);
            g.FillEllipse(plate_lgb, plate_rect);
            plate_lgb.Dispose();

            //表盘边框
            Pen plate_border_pen = new Pen(Color.FromArgb(170, this.StyleAppearance.PlateBackColor), 1);
            g.DrawEllipse(plate_border_pen, plate_rect);
            plate_border_pen.Dispose();

            //角度针
            PointF pointer_point = ControlHelper.CalculatePointForAngle(plate_center_point, scale_plate_radius - scale_pointer_padding - scale_pointer_radius, this.ReferenceAngle + this.Value);
            SolidBrush pointer_sb = new SolidBrush(this.StyleAppearance.PointerColor);
            g.FillEllipse(pointer_sb, new RectangleF(pointer_point.X - scale_pointer_radius, pointer_point.Y - scale_pointer_radius, scale_pointer_radius * 2, scale_pointer_radius * 2));
            pointer_sb.Dispose();

            //文本
            if (this.ValueVisible)
            {
                string text_str = this.Value.ToString();
                if ((Events[EventValueFormat] as EventHandler) != null)
                {
                    IntAngleFormatEventArgs arg = new IntAngleFormatEventArgs(this.Value, text_str);
                    this.OnValueFormat(arg);
                    text_str = arg.AngleFormat;
                }
                NativeMethods.TEXTMETRIC font_metrics = ControlHelper.GetFontMetrics(this.Handle, this.Font);
                Size text_size = new Size((int)Math.Ceiling(g.MeasureString(text_str, this.Font, int.MaxValue, StringFormat.GenericTypographic).Width), font_metrics.GetFontRealHeight());

                SolidBrush text_sb = new SolidBrush(this.StyleAppearance.TextColor);
                g.DrawString(text_str, this.Font, text_sb, new PointF(plate_center_point.X - text_size.Width / 2f, plate_center_point.Y - text_size.Height / 2), StringFormat.GenericTypographic);
                text_sb.Dispose();
            }

        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);

            this.mousedownobject = false;
            this.pointer_lock_area = 0;
        }

        protected override void OnEnabledChanged(EventArgs e)
        {
            base.OnEnabledChanged(e);

            if (!this.Enabled)
            {
                this.mousedownobject = false;
                this.pointer_lock_area = 0;
            }
        }

        protected override void OnVisibleChanged(EventArgs e)
        {
            base.OnVisibleChanged(e);

            if (!this.Visible)
            {
                this.mousedownobject = false;
                this.pointer_lock_area = 0;
            }
        }

        protected override void OnParentChanged(EventArgs e)
        {
            base.OnParentChanged(e);

            if (this.Parent == null)
            {
                this.mousedownobject = false;
                this.pointer_lock_area = 0;
            }
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);

            this.mousedownobject = false;
            this.pointer_lock_area = 0;
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (!this.ReadOnly)
            {
                if (!this.Focused)
                {
                    this.Focus();
                }

                if (e.Button == MouseButtons.Left)
                {
                    Point plate_center_point = new Point(this.ClientRectangle.X + this.ClientRectangle.Width / 2, this.ClientRectangle.Y + this.ClientRectangle.Height / 2);
                    this.mousedownobject = true;
                    this.mousedownoangledisparity = (int)ControlHelper.CalculateAngleForPoint(plate_center_point, e.Location) - this.Value;
                    this.pointer_last_area = this.GetPointerArea(this.value);
                    this.pointer_current_area = this.pointer_last_area;
                }
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            this.mousedownobject = false;
            this.pointer_lock_area = 0;

            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            if (!this.ReadOnly)
            {
                if (this.mousedownobject)
                {
                    Point plate_center_point = new Point(this.ClientRectangle.X + this.ClientRectangle.Width / 2, this.ClientRectangle.Y + this.ClientRectangle.Height / 2);
                    int current_angle = (360 + (int)ControlHelper.CalculateAngleForPoint(plate_center_point, e.Location) - (this.mousedownoangledisparity)) % 360;

                    if (this.AllowLoopChanged)
                    {
                        if (this.Value != current_angle)
                        {
                            this.Value = current_angle;
                            this.Invalidate();
                        }
                    }
                    else
                    {
                        int pointer_current_area_tmp = GetPointerArea(current_angle);
                        if (this.pointer_current_area != pointer_current_area_tmp)
                        {
                            this.pointer_last_area = this.pointer_current_area;
                            this.pointer_current_area = pointer_current_area_tmp;
                        }

                        if (this.pointer_lock_area == 0)//鼠标操作没有跨越过最大最小边界
                        {
                            if (pointer_last_area == 4 && this.pointer_current_area == 1)//鼠标进行角度增加操作并越过最大角度值
                            {
                                this.pointer_lock_area = 4;

                                this.Value = 360;
                                this.Invalidate();
                            }
                            else if (pointer_last_area == 1 && this.pointer_current_area == 4)//鼠标进行角度减小操作并越过最小角度值
                            {
                                this.pointer_lock_area = 1;

                                this.Value = 0;
                                this.Invalidate();
                            }
                            else//鼠标在允许范围内增加或减小角度值
                            {
                                this.Value = (int)current_angle;
                                this.Invalidate();
                            }
                        }
                        else//鼠标操作有跨越过最大最小边界
                        {
                            if (this.pointer_lock_area == 4)//曾经越过最大值边界
                            {
                                if (this.pointer_last_area == 1 && this.pointer_current_area == 4)//只有鼠标有1区移动到4区才允许解锁4区个更改角度值
                                {
                                    this.pointer_lock_area = 0;
                                    this.pointer_last_area = this.pointer_current_area;

                                    this.Value = (int)current_angle;
                                    this.Invalidate();
                                }
                            }
                            else if (this.pointer_lock_area == 1)//曾经越过最小值边界
                            {
                                if (this.pointer_last_area == 4 && this.pointer_current_area == 1)//只有鼠标有4区移动到1区才允许解锁1区个更改角度值
                                {
                                    this.pointer_lock_area = 0;
                                    this.pointer_last_area = this.pointer_current_area;

                                    this.Value = (int)current_angle;
                                    this.Invalidate();
                                }
                            }
                        }
                    }
                }
            }
        }

        #endregion

        #region 虚方法

        protected virtual void OnValueChanged(EventArgs e)
        {
            EventHandler handler = Events[EventValueChanged] as EventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        protected virtual void OnValueFormat(IntAngleFormatEventArgs e)
        {
            ValueFormatEventHandler handler = Events[EventValueFormat] as ValueFormatEventHandler;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion

        #region 私有方法

        /// <summary>
        /// 获取角度针所在区域（由参考角度开始，90度为一个区，一个四个区域）
        /// </summary>
        /// <param name="angle">相对于参考角度的角度值</param>
        /// <returns></returns>
        private int GetPointerArea(double angle)
        {
            if (angle <= 90)
            {
                return 1;
            }
            else if (angle <= 180)
            {
                return 2;
            }
            else if (angle <= 270)
            {
                return 3;
            }
            return 4;
        }

        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinBackColor = Color.Empty;
            private readonly Color defaultBackColor = SystemColors.Control;
            private Color backColor = Color.Empty;
            /// <summary>
            /// 背景颜色
            /// </summary>
            [Description("背景颜色")]
            [PropertyOrder(-195)]
            [SkinProperty(true, true)]
            public Color BackColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore() && this.skinBackColor != Color.Empty)
                    {
                        return this.skinBackColor;
                    }

                    if (this.backColor != Color.Empty)
                    {
                        return this.backColor;
                    }

                    if (((Control)this.owner).Parent != null)
                    {
                        return ((Control)this.owner).Parent.BackColor;
                    }

                    return this.defaultBackColor;
                }
                set
                {
                    if (this.backColor == value)
                        return;

                    this.backColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeBackColor()
            {
                return this.backColor != Color.Empty;
            }
            private void ResetBackColor()
            {
                this.backColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinTextColor = Color.Empty;
            private readonly Color defaultTextColor = SystemColors.Window;
            private Color textColor = Color.Empty;
            /// <summary>
            /// 文本颜色
            /// </summary>
            [Description("文本颜色")]
            [PropertyOrder(-194)]
            [SkinProperty(true, false)]
            public Color TextColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinTextColor;
                    }

                    if (this.textColor != Color.Empty)
                    {
                        return this.textColor;
                    }

                    return this.defaultTextColor;
                }
                set
                {
                    if (this.textColor == value)
                        return;

                    this.textColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeTextColor()
            {
                return this.textColor != Color.Empty;
            }
            private void ResetTextColor()
            {
                this.textColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinPlateBackColor = Color.Empty;
            private readonly Color defaultPlateBackColor = SystemColors.ActiveCaption;
            private Color plateBackColor = Color.Empty;
            /// <summary>
            /// 表盘背景颜色
            /// </summary>
            [Description("表盘背景颜色")]
            [PropertyOrder(-192)]
            [SkinProperty(true, false)]
            public Color PlateBackColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinPlateBackColor;
                    }

                    if (this.plateBackColor != Color.Empty)
                    {
                        return this.plateBackColor;
                    }

                    return this.defaultPlateBackColor;
                }
                set
                {
                    if (this.plateBackColor == value)
                        return;

                    this.plateBackColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializePlateBackColor()
            {
                return this.plateBackColor != Color.Empty;
            }
            private void ResetPlateBackColor()
            {
                this.plateBackColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinPlateBackShadowColor = Color.Empty;
            private readonly Color defaultPlateBackShadowColor = SystemColors.GradientInactiveCaption;
            private Color plateBackShadowColor = Color.Empty;
            /// <summary>
            /// 表盘背景阴影颜色
            /// </summary>
            [Description("表盘背景阴影颜色")]
            [PropertyOrder(-190)]
            [SkinProperty(true, false)]
            public Color PlateBackShadowColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinPlateBackShadowColor;
                    }

                    if (this.plateBackShadowColor != Color.Empty)
                    {
                        return this.plateBackShadowColor;
                    }

                    return this.defaultPlateBackShadowColor;
                }
                set
                {
                    if (this.plateBackShadowColor == value)
                        return;

                    this.plateBackShadowColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializePlateBackShadowColor()
            {
                return this.plateBackShadowColor != Color.Empty;
            }
            private void ResetPlateBackShadowColor()
            {
                this.plateBackShadowColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinPointerColor = Color.Empty;
            private readonly Color defaultPointerColor = SystemColors.ActiveCaption;
            private Color pointerColor = Color.Empty;
            /// <summary>
            /// 角度针颜色
            /// </summary>
            [Description("角度针颜色")]
            [PropertyOrder(-188)]
            [SkinProperty(true, false)]
            public Color PointerColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinPointerColor;
                    }

                    if (this.pointerColor != Color.Empty)
                    {
                        return this.pointerColor;
                    }

                    return this.defaultPointerColor;
                }
                set
                {
                    if (this.pointerColor == value)
                        return;

                    this.pointerColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializePointerColor()
            {
                return this.pointerColor != Color.Empty;
            }
            private void ResetPointerColor()
            {
                this.pointerColor = Color.Empty;
                this.Invalidate();
            }

            private Color skinReferenceAngleLineColor = Color.Empty;
            private readonly Color defaultReferenceAngleLineColor = SystemColors.ActiveCaption;
            private Color referenceAngleLineColor = Color.Empty;
            /// <summary>
            /// 参考角度线颜色
            /// </summary>
            [Description("参考角度线颜色")]
            [PropertyOrder(-186)]
            [SkinProperty(true, false)]
            public Color ReferenceAngleLineColor
            {
                get
                {
                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinReferenceAngleLineColor;
                    }

                    if (this.referenceAngleLineColor != Color.Empty)
                    {
                        return this.referenceAngleLineColor;
                    }

                    return this.defaultReferenceAngleLineColor;
                }
                set
                {
                    if (this.referenceAngleLineColor == value)
                        return;

                    this.referenceAngleLineColor = value;
                    this.Invalidate();
                }
            }
            private bool ShouldSerializeReferenceAngleLineColor()
            {
                return this.referenceAngleLineColor != Color.Empty;
            }
            private void ResetReferenceAngleLineColor()
            {
                this.referenceAngleLineColor = Color.Empty;
                this.Invalidate();
            }

            #endregion

        }

        #endregion

    }
}
